package org.cheetahworkflow.designer.figure;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.cheetahworkflow.designer.model.RapidView;
import org.cheetahworkflow.designer.ui.WorkflowChartEditor;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.text.AbstractFlowBorder;
import org.eclipse.draw2d.text.BlockFlow;
import org.eclipse.draw2d.text.FlowPage;
import org.eclipse.draw2d.text.TextFlow;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;

public class RapidViewFigure extends FlowPage {

	private static final Color BACKGROUND_COLOR = new Color(Display.getCurrent(), 0xFF, 0xFF, 0xCC);
	
	private static final int RAPID_VIEW_WIDTH = 360;
	
	private static final int RAPID_VIEW_HEIGHT = 220;
	
	private static final int HOST_PADDING = 5;
	
	private static class SolidTextFlow extends TextFlow {
		protected SolidTextFlow() {
			super();
			setBorder(new AbstractFlowBorder() {
				@Override
				public Insets getInsets(IFigure figure) {
					return new Insets(0, 4, 0, 4);
				}
				
				@Override
				public boolean isOpaque() {
					return true;
				}
			});
		}
	}
	
	private TextFlow nodeTypeLabel = new SolidTextFlow();
	
	private TextFlow captionLabel = new SolidTextFlow();
	
	private TextFlow descriptionLabel = new SolidTextFlow();
	
	private TextFlow mappingClassLabel = new SolidTextFlow();
	
	private TextFlow parameterLabel = new SolidTextFlow();
	
	private TextFlow refLabel = new SolidTextFlow();
	
	private TextFlow refClasspathLabel = new SolidTextFlow();
	
	private TextFlow defaultConditionLabel = new SolidTextFlow();
	
	public RapidViewFigure() {
		setForegroundColor(ColorConstants.black);
		setBackgroundColor(BACKGROUND_COLOR);
		setBorder(new LineBorder(1));
		setOpaque(true);
		setSize(RAPID_VIEW_WIDTH, RAPID_VIEW_HEIGHT);
	}
	
	public void setAllText(RapidView rapidView) {
		Field[] fields = RapidView.class.getFields();
		for(Field field: fields) {
			try {
				String fieldName = field.getName();
				String value = (String) field.get(rapidView);
				if (value != null && !value.isEmpty()) {
					Method method = getClass().getMethod("set" + ("" + fieldName.charAt(0)).toUpperCase() + fieldName.substring(1), new Class[] {String.class});
					method.invoke(this, value);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public void render(RapidView rapidView) {
		WorkflowChartEditor editor = rapidView.getChart().getWorkflowChartEditor();
		Rectangle bounds = editor.getViewportBounds();
		Point canvasStartPoint = new Point(bounds.x, bounds.y);
		Point canvasEndPoint = new Point(bounds.x + bounds.width, bounds.y + bounds.height);
		
		int horizonalScrool = editor.getHorizontalScroll();
		int verticalScroll = editor.getVerticalScroll();
		Rectangle hostBounds = rapidView.getHostBounds();
		
		Point location = findValidLocation(
				canvasStartPoint,
				canvasEndPoint,
				hostBounds.getTopRight().getTranslated(HOST_PADDING - horizonalScrool, -verticalScroll),
				hostBounds.getTopLeft().getTranslated(-HOST_PADDING - RAPID_VIEW_WIDTH - horizonalScrool, -verticalScroll),
				hostBounds.getBottomRight().getTranslated(HOST_PADDING - horizonalScrool, -RAPID_VIEW_HEIGHT - verticalScroll),
				hostBounds.getBottomLeft().getTranslated(-HOST_PADDING - RAPID_VIEW_WIDTH - horizonalScrool, -RAPID_VIEW_HEIGHT - verticalScroll));
		setLocation(location.getTranslated(horizonalScrool, verticalScroll));
	}
	
	private Point findValidLocation(Point canvasStartPoint, Point canvasEndPoint, Point... testPoints) {
		for(Point point: testPoints) {
			Point bottomRightPoint = new Point(point.x + RAPID_VIEW_WIDTH, point.y + RAPID_VIEW_HEIGHT);
			if (canvasStartPoint.x <= point.x
				&& canvasStartPoint.y <= point.y
				&& canvasEndPoint.x >= bottomRightPoint.x
				&& canvasEndPoint.y >= bottomRightPoint.y) {
				return point;
			}
		}
		return testPoints[0];
	}
	
	public void setNodeType(String nodeType) {
		add(nodeTypeLabel);
		nodeTypeLabel.setText("TYPE: " + nodeType + "\n");
		add(new BlockFlow());
		repaint();
	}
	
	public void setCaption(String caption) {
		add(captionLabel);
		captionLabel.setText("CAPTION: " + caption + "\n");
		add(new BlockFlow());
		repaint();
	}
	
	public void setDescription(String descritpion) {
		add(descriptionLabel);
		descriptionLabel.setText("DESCRIPTION: " + descritpion + "\n");
		add(new BlockFlow());
		repaint();
	}
	
	public void setMappingClass(String mappingClass) {
		add(mappingClassLabel);
		mappingClassLabel.setText("CLASS: " + mappingClass + "\n");
		add(new BlockFlow());
		repaint();
	}
	
	public void setParameter(String parameter) {
		add(parameterLabel);
		parameterLabel.setText("PARAMETER: " + parameter + "\n");
		add(new BlockFlow());
		repaint();
	}
	
	public void setRef(String ref) {
		add(refLabel);
		refLabel.setText("REF: " + ref + "\n");
		add(new BlockFlow());
		repaint();
	}
	
	public void setRefClasspath(String classpath) {
		add(refClasspathLabel);
		refClasspathLabel.setText("REF CLASSPATH: " + classpath + "\n");
		add(new BlockFlow());
		repaint();
	}
	
	public void setDefaultCondition(String defaultCondition) {
		add(defaultConditionLabel);
		defaultConditionLabel.setText("DEFAULT CONDITION: " + defaultCondition);
		add(new BlockFlow());
		repaint();
	}
}
